{
  Базовые функции конфигурации и определения плагинов

 TinlConfiguration - Описание базовой конфигурации

 TPluginInfo - Информация о подключаемом модуле
 TinlPlugin - Подключаемый модуль
 TinlModule - Статический модуль

   версия 0.2 март 2011 prodg@ya.ru D.Kondakov
}
unit IIntgrlBaseCnfg;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, IniFiles, IIntgrlTypes, IIntgrlBaseDefs, IIntgrlBaseParms;

{$i calcconfig.inc}

type
  TEchoLevel = (elSilent, elError, elWarng, elHint, elInfo, elAll);

  TinlPlugin = class;

  { TinlConfiguration }

  TinlConfiguration = class{$ifdef iiThreadCfg}(TThread){$endif}
    constructor Create;
    destructor Destroy; override;
    procedure doError(s: TinlStringType);        // Произошла ошибка
    procedure doWarng(s: TinlStringType);        // Выдать предупреждение
    procedure doHint(s: TinlStringType);         // Дать подсказку
    procedure doInfo(s: TinlStringType);         // Сообщить информацию
    {$ifdef iiDebugLog}
    procedure doDebug(s: TinlStringType);        // Сообщить информацию
    {$endif}

    procedure RegPlugin(aPlgn: TinlPlugin);
    procedure UnRegPlugin(aPlgn: TinlPlugin);
    procedure doIdle;
    procedure SendSignal(snlRcpnt:TinlNameType; snlMsg: TinlStringType);

    function GetParam(ParamInfo: PcfgParmtrInfo; const pValue: pointer = nil): TinlStringType;
    function GetLogicParam(ParamName: TinlNameType; const DefVal: TinlLogicType = true): TinlLogicType;
    function GetStringParam(ParamName: TinlNameType; DefVal: TinlStringType): TinlStringType;
    function GetIntegerParam(ParamName: TinlNameType; const DefVal: TinlIntegerType = 0): TinlIntegerType;
  private
    FCfgFileName: TextLongNameType;              // Имя файла конфигурации
    FRunLog: ^Text;                              // Файл журнала
    FLogActive: Boolean;                         // Журнал открыт
    FEchoLog: TEchoLevel;                        // Дублировать вывод в файл
    FEchoScrn: TEchoLevel;                       // Дублировать вывод на терминал
    FErrorsCnt: TinlIntegerType;                 // Число ошибок
    FWarningsCnt: TinlIntegerType;               // Число предупреждений
    FSignalsCnt: TinlIntegerType;                // Число необработанных сигналов
    FMSGQueue: TStringList;                      // Очередь сообщений
    FParams: TStringList;                        // Список всех параметров конфигурации
    FSections: TStringList;
    FAvailPlugins: TFPList;                      // Список доступных расширений
    FActvPlugins: TStringList;                   // Список активированных модулей
    FIDList: TFPList;                            // Список используемых идентификаторов
    procedure StartLoging(aLogFileName: TextLongNameType);
    procedure StopLoging;
  protected
    {$ifdef iiThreadCfg}
    procedure Execute; override;
    {$endif}
    procedure StoreCfgToFile(aCfgFileName: TextLongNameType);
    function getHead: TinlStringType; virtual; abstract;
    function getEnd: TinlStringType; virtual; abstract;

    procedure GetDefParams; virtual;
    procedure ReadParamsFromCmdLine; virtual;
    procedure ReadParamsFromEnvrnmnt; virtual;
    procedure ReadParamsFromCfgFile(aCfgFile: TIniFile); virtual;
    procedure WriteParamsToCfgFile(aCfgFile: TIniFile); virtual;

    function postError(s: TinlStringType): TinlLogicType; virtual;
    function postWarng(s: TinlStringType): TinlLogicType; virtual;
    function postHint(s: TinlStringType): TinlLogicType; virtual;
    function postInfo(s: TinlStringType): TinlLogicType; virtual;
    {$ifdef iiDebugLog}
    function postDebug(s: TinlStringType): TinlLogicType; virtual;
    {$endif}

    procedure DetachPlugins; virtual;
    procedure ProceedSignals;
    procedure postSignal(snlRcpnt:TinlNameType; snlMsg: TinlStringType); virtual;
    function GetNewID: TinlID;
    function RegisterID(aID: TinlID): TinlID;
  public
    property EchoLog: TEchoLevel read FEchoLog default elAll;
    property EchoScrn: TEchoLevel read FEchoScrn default elAll;
    property numErrors: TinlIntegerType read FErrorsCnt;
    property numWarnings: TinlIntegerType read FWarningsCnt;
    property numSignals: TinlIntegerType read FSignalsCnt;
    property CfgFileName: TextLongNameType read FCfgFileName;
    property CfgParams: TStringList read FParams;
  end;

  TPluginInfo = record
    plgName: TinlNameType;
    plgVer: TinlModifctn;
    plgFile: TextLongNameType;
    // Параметры необходимые для иннициализации
    // Зависимости от других элементов конфигурации
  end;

  TUnitState = (sGood, sInit, sKill, sReset, sWork, sError, sData, sNUL);
  TUnitType = (uModule, mdLOG, mdEXEC, mdSOLV, mdDB, mdLIB, mdHIST, mdACCNT, mdCONS, uPlugin, pgBase, pgSearch, pgUser);

  { TinlPlugin }

  TinlPlugin = class
    constructor Create(aType: TUnitType; aName: TinlNameType);
    destructor Destroy; override;

    procedure GetDefParams(DefParams: TStrings); virtual; abstract;
    function CheckParams: TinlLogicType; virtual; abstract;
    procedure AddDefParams(Params: TStringList); virtual; abstract;
    procedure ResetParams; virtual; abstract;

    procedure ProceedSignal(snlMsg: TinlStringType); virtual; abstract;

    function GetCfgParam(ParamInfo: PcfgParmtrInfo): TinlStringType;
    function GetLogicCfgParam(ParamName: TinlNameType; DefVal: TinlLogicType): TinlLogicType;
    function GetStringCfgParam(ParamName: TinlNameType; DefVal: TinlStringType): TinlStringType;
    function GetIntegerCfgParam(ParamName: TinlNameType; DefVal: TinlIntegerType): TinlIntegerType;
  private
    FPluged: TinlLogicType;
    FConfiguration: TinlConfiguration;
    FUnitType: TUnitType;
    FUnitName: TinlNameType;
    FUnitStatus: TUnitState;
    FUnitInfo: TPluginInfo;
    FUnitLogPrfx: TinlNameType;
    FUnitCfgPrfx: TinlNameType;
    FChilds: TFPList;
  protected
    procedure goError(s: TinlStringType);
    procedure goWarng(s: TinlStringType);
    procedure goHint(s: TinlStringType);
    procedure goInfo(s: TinlStringType);
    {$ifdef iiDebugLog}
    procedure goDebug(s: TinlStringType);
    {$endif}
    function GetUnitVersion: TinlModifctn; virtual; abstract;
    procedure DataInit; virtual; abstract;
    procedure DataDone; virtual; abstract;
    function PlugIn(aCfg: TinlConfiguration): TinlLogicType;
    procedure regChild(aChild: TinlPlugin);
    procedure sndSignal(snlRcpnt:TinlNameType; snlMsg: TinlStringType);
  public
    property untType: TUnitType read FUnitType;
    property untStatus: TUnitState read FUnitStatus;
    property untName: TinlNameType read FUnitName;
    property untVer: TinlModifctn read GetUnitVersion;
  end;

  TModuleType = (mLOG, mEXEC, mSOLV, mDB, mLIB, mHIST, mACCNT, mCONS);

  { TinlModule }

  TinlModule = class(TinlPlugin)
    constructor Create(wCfg: TinlConfiguration);
    destructor Destroy; override;
  protected
    function GetModuleType: TModuleType; virtual; abstract;
  public
    property modType: TModuleType read GetModuleType;
  end;

const
  msgALL = '*';

implementation

uses
  StrUtils, FileUtil;

resourcestring
  rlogNowDelim = ' : ';
  rlogStart = 'FIRST =>';
  rlogFinish = 'LAST <=';
  rlogErrorFile = 'Error open file:';

  modCfgPrfx = 'MOD_';
  cfgPrfx = 'IINTEGRAL_';
  IIDISABLE = 'DISABLED';

const
  modUnits: array [TModuleType] of TUnitType = (mdLOG, mdEXEC, mdSOLV, mdDB, mdLIB,
    mdHIST, mdACCNT, mdCONS);

  modNames: array [TModuleType] of string = (LOGmodName, EXECmodName, SOLVmodName,
    DBmodName, LIBmodName, HISTmodName, ACCNTmodName, CONSmodName);

  untStatusNames: array [TUnitState] of string = ('Good', 'Init', 'Kill', 'Reset',
    'Work', 'Error', 'Data', 'NUL');

  pstError = 'ERROR'+pstDelim;
  pstWarng = 'Warn'+pstDelim;
  pstHint = 'Hint'+pstDelim;
  pstInfo = 'Info'+pstDelim;
  pstDebg = 'DBG'+pstDelim;
  pstPlgn = 'PLGN';
  pstCfg = 'CFG';
  pstMod = 'MODL';
  cfgError = pstCfg+b;
  cfgWarng = pstCfg+b;
  cfgHint = pstCfg+b;
  cfgInfo = pstCfg+b;
  plgError = pstPlgn+pstDelim;
  plgWarng = pstPlgn+pstDelim;
  plgHint = pstPlgn+pstDelim;
  plgInfo = pstPlgn+pstDelim;
  cfgBegin = 'Bgn'+b+pstCfg;
  cfgEnd = 'End'+b+pstCfg;
  cfgProbe = 'Probe'+b+pstCfg;
  cfgDone = 'Done'+b+pstCfg;
  cfgINI = 'INI'+b+pstCfg;

  prmLogName: TcfgParmtrInfo = (
    prmName: 'LOG_NAME';
    prmValue: pFile;
    prmCaption: 'Файл журнала';
    prmComment: 'Имя файла для записи ошибок, предупреждений, информации и отладочной информации.';
    DefValue: prgCfgFileName;
    ChkValue: false;
    prmMngbl: true;
  );

{ TinlConfiguration }

constructor TinlConfiguration.Create;
var
  IniF: TIniFile;
begin
  writeln(StdOut, getHead);  // Выводит заголовок
  {$ifdef iiThreadCfg}
  inherited Create(false);
  {$else}
  inherited Create;
  {$endif}

  FEchoLog := elAll;
  FEchoScrn := elAll;
  StartLoging(logFileName);  // Открывает файл журнала
  doInfo(cfgBegin);          // Bgn CFG

  FAvailPlugins := TFPList.Create;   // Составляет список доступных плагинов (указанных,локально,глобально)

  FParams := TStringList.Create;
  ReadParamsFromEnvrnmnt;    // Читает параметры из переменных окружения
  ReadParamsFromCmdLine;     // Читает параметры из командной строки

  FCfgFileName := ExpandFileNameUTF8(prgCfgFileName); // пробуем cfgFile
  doInfo(cfgProbe+pstDelim+FCfgFileName);
  if FileExistsUTF8(FCfgFileName) then doInfo(cfgINI+pstDelim+FCfgFileName)
  else begin // пробуем ~/appNmae/cfgFile
    FCfgFileName := ExpandFileNameUTF8(GetAppConfigDir(false)+prgCfgFileName);
    doInfo(cfgProbe+pstDelim+FCfgFileName);
    if FileExistsUTF8(FCfgFileName) then doInfo(cfgINI+pstDelim+FCfgFileName)
    else begin // пробуем /etc/appNmae/cfgFile
      FCfgFileName := ExpandFileNameUTF8(GetAppConfigDir(true)+prgCfgFileName);
      doInfo(cfgProbe+pstDelim+FCfgFileName);
      if FileExistsUTF8(FCfgFileName) then doInfo(cfgINI+pstDelim+FCfgFileName)
      else begin // пробуем ~/appNmae/appCfg
        FCfgFileName := GetAppConfigFile(false,true);
        doInfo(cfgProbe+pstDelim+FCfgFileName);
        if FileExistsUTF8(FCfgFileName) then doInfo(cfgINI+pstDelim+FCfgFileName)
        else begin // пробуем /etc/appNmae/appCfg
          FCfgFileName := GetAppConfigFile(true,true);
          doInfo(cfgProbe+pstDelim+FCfgFileName);
          if FileExistsUTF8(FCfgFileName) then doInfo(cfgINI+pstDelim+FCfgFileName)
          else begin
            doError(logNoINI);
            FCfgFileName := ExpandFileNameUTF8(prgCfgFileName); // создаем cfgFile
            doInfo('Create file'+pstDelim+FCfgFileName);
            IniF := TIniFile.Create(FCfgFileName);
            try
              IniF.WriteString('IINTEGRAL', 'NEW', '1');
            finally
              IniF.Free;
            end;
          end;
        end;
      end;
    end;
  end;
  IniF := TIniFile.Create(FCfgFileName);
  try
    ReadParamsFromCfgFile(IniF);
  finally
    IniF.Free;
  end;

  FMSGQueue := TStringList.Create;           // Инициализирует очередь сообщений
  FMSGQueue.Capacity := 100000;
  FSignalsCnt := 0;

  FActvPlugins := TStringList.Create;
  FActvPlugins.Duplicates := dupError;

  FIDList := TFPList.Create;

  doInfo(cfgDone);
end;

destructor TinlConfiguration.Destroy;
begin
  ProceedSignals;            // Завершает обработку сообщений
  {$ifdef iiThreadCfg}  {Suspend;}  {$endif}
  FreeAndNil(FMSGQueue);

  FreeAndNil(FActvPlugins);

  FreeAndNil(FAvailPlugins);

  StoreCfgToFile(FCfgFileName);
  FreeAndNil(FParams);

  FreeAndNil(FIDList);

  StopLoging;                // Закрывает файл журнала
  doInfo(cfgEnd);
  inherited Destroy;
  writeln(StdOut, getEnd);
end;

procedure TinlConfiguration.doError(s: TinlStringType);
begin
  Inc(FErrorsCnt);
  postError(s);
end;

procedure TinlConfiguration.doWarng(s: TinlStringType);
begin
  Inc(FWarningsCnt);
  postWarng(s);
end;

procedure TinlConfiguration.doHint(s: TinlStringType);
begin
  postHint(s);
end;

procedure TinlConfiguration.doInfo(s: TinlStringType);
begin
  postInfo(s);
end;

{$ifdef iiDebugLog}
procedure TinlConfiguration.doDebug(s: TinlStringType);
begin
  postDebug(s);
end;
{$endif}

procedure TinlConfiguration.SendSignal(snlRcpnt: TinlNameType; snlMsg: TinlStringType);
begin
  FSignalsCnt := FMSGQueue.Add(snlRcpnt+eq+snlMsg);
end;

procedure TinlConfiguration.ProceedSignals;
var
  ds, ms: String;
begin
  while FSignalsCnt>0 do begin
    FMSGQueue.GetNameValue(FMSGQueue.Count-FSignalsCnt, ds, ms);
    postSignal(ds, ms);
    dec(FSignalsCnt);
  end;
end;

function TinlConfiguration.GetParam(ParamInfo: PcfgParmtrInfo; const pValue: pointer): TinlStringType;
begin
  result := ParamInfo^.DefValue;
  case ParamInfo^.prmValue of
    pLogic: if pValue<>nil then begin
        TinlLogicType(pValue^) := GetLogicParam(ParamInfo^.prmName, s2b(result));
        result := b2s(TinlLogicType(pValue^));
      end else result := b2s(GetLogicParam(ParamInfo^.prmName, s2b(result)));
    pNumber: if pValue<>nil then begin
        TinlIntegerType(pValue^) := GetIntegerParam(ParamInfo^.prmName, StrToInt(result));
        result := i2s(TinlIntegerType(pValue^));
      end else result := i2s(GetIntegerParam(ParamInfo^.prmName, StrToInt(result)));
    else result := GetStringParam(ParamInfo^.prmName, result);
  end;
end;

function TinlConfiguration.GetLogicParam(ParamName: TinlNameType; const DefVal: TinlLogicType): TinlLogicType;
begin
  result := DefVal;
end;

function TinlConfiguration.GetStringParam(ParamName: TinlNameType; DefVal: TinlStringType): TinlStringType;
begin
  result := DefVal;
end;

function TinlConfiguration.GetIntegerParam(ParamName: TinlNameType; const DefVal: TinlIntegerType): TinlIntegerType;
begin
  result := DefVal;
end;

procedure TinlConfiguration.RegPlugin(aPlgn: TinlPlugin);
begin
  if aPlgn.PlugIn(Self) then FActvPlugins.AddObject(aPlgn.untName, aPlgn);
end;

procedure TinlConfiguration.UnRegPlugin(aPlgn: TinlPlugin);
var
  i: integer;
begin
  if FActvPlugins.Find(aPlgn.untName, i) then FActvPlugins.Delete(i);
end;

procedure TinlConfiguration.doIdle;
begin

end;

procedure TinlConfiguration.StartLoging(aLogFileName: TextLongNameType);
begin
  new(FRunLog);
  try
    Assign(FRunLog^, aLogFileName);
    if FileExistsUTF8(aLogFileName) then Append(FRunLog^)
    else Rewrite(FRunLog^);
    writeln(FRunLog^, rlogStart+b+DateTimeToStr(Now));
  except
    Freemem(FRunLog);
    FRunLog := nil;
    postError(rlogErrorFile+b+aLogFileName);
  end;
  FLogActive := assigned(FRunLog);
end;

procedure TinlConfiguration.StopLoging;
begin
  if FLogActive then begin
    writeln(FRunLog^, rlogFinish+b+DateTimeToStr(Now));
    Close(FRunLog^);
    Dispose(FRunLog);
    FLogActive := false;
  end;
  FRunLog := nil;
end;

procedure TinlConfiguration.Execute;
begin
  doIdle;
end;

procedure TinlConfiguration.StoreCfgToFile(aCfgFileName: TextLongNameType);
var
  i: integer;
  IniF: TIniFile;
begin
  if FParams.Count=0 then exit;
  IniF := TIniFile.Create(aCfgFileName);
  try
    for i:=0 to FParams.Count-1 do begin
      { IniF.WriteString(FCfgPrfx, DBmodName, '1'); }
    end;
  finally
    IniF.Free;
  end;
end;

procedure TinlConfiguration.GetDefParams;
begin
  CfgParams.Add('LOG_NAME='+prgCfgFileName);
end;

procedure TinlConfiguration.ReadParamsFromCmdLine;
var
  i: integer;
  s: string;
begin
  for i:= 1 to Paramcount do begin
    s := copy(ParamStrUTF8(i),1,10);
    if s = '--default ' then begin
//      FCntxName := copy(ParamStrUTF8(i),11,20);
    end else if s = '--disable-' then begin
{      s := copy(ParamStrUTF8(i),11,4);
      if s = 'db' then fdb := false
      else if s = 'hist' then fhist := false;}
    end;// else if s = '--create-db' then CreateNewDB;
  end;
end;

procedure TinlConfiguration.ReadParamsFromEnvrnmnt;
begin
//  FCntxName := GetEnvironmentVariableUTF8(FCfgPrfx + 'DEFAULT_CONTEXT');
//  if FCntxName = '' then begin
//    WriteRunLog(logNoContext);
//    FCntxName := CfgDfltCntxt;
//  end;
end;

procedure TinlConfiguration.ReadParamsFromCfgFile(aCfgFile: TIniFile);
begin
{ if not fdb then fdb := aCfgFile.ReadString(FCfgPrfx, DBmodName, '1') <> IIDISABLE;
  if not faccnt then faccnt := aCfgFile.ReadString(FCfgPrfx, ACCNTmodName, '1') <> IIDISABLE;
  if not fhist then fhist := aCfgFile.ReadString(FCfgPrfx, HISTmodName, '1') <> IIDISABLE;}
end;

procedure TinlConfiguration.WriteParamsToCfgFile(aCfgFile: TIniFile);
begin
{ if not fdb then fdb := aCfgFile.ReadString(FCfgPrfx, DBmodName, '1') <> IIDISABLE;
  if not faccnt then faccnt := aCfgFile.ReadString(FCfgPrfx, ACCNTmodName, '1') <> IIDISABLE;
  if not fhist then fhist := aCfgFile.ReadString(FCfgPrfx, HISTmodName, '1') <> IIDISABLE;}
end;

function TinlConfiguration.postError(s: TinlStringType): TinlLogicType;
begin
  result := false;
  if FEchoScrn > elSilent then begin
    writeln(StdOut, pstError+s);
    result := true;
  end;
  if FLogActive and (FEchoLog > elSilent) then begin
    writeln(FRunLog^, pstError+s);
    result := true;
  end;
end;

function TinlConfiguration.postWarng(s: TinlStringType): TinlLogicType;
begin
  result := false;
  if FEchoScrn > elError then begin
    writeln(StdOut, pstWarng+s);
    result := true;
  end;
  if FLogActive and (FEchoLog > elError) then begin
    writeln(FRunLog^, pstWarng+s);
    result := true;
  end;
end;

function TinlConfiguration.postHint(s: TinlStringType): TinlLogicType;
begin
  result := false;
  if FEchoScrn > elWarng then begin
    writeln(StdOut, pstHint+s);
    result := true;
  end;
  if FLogActive and (FEchoLog > elWarng) then begin
    writeln(FRunLog^, pstHint+s);
    result := true;
  end;
end;

function TinlConfiguration.postInfo(s: TinlStringType): TinlLogicType;
begin
  result := false;
  if FEchoScrn > elHint then begin
    writeln(StdOut, pstInfo+s);
    result := true;
  end;
  if FLogActive and (FEchoLog > elHint) then begin
    writeln(FRunLog^, pstInfo+s);
    result := true;
  end;
end;

{$ifdef iiDebugLog}
function TinlConfiguration.postDebug(s: TinlStringType): TinlLogicType;
begin
  result := false;
  if FEchoScrn > elInfo then begin
    writeln(StdOut, pstDebg+s);
    result := true;
  end;
  if FLogActive and (FEchoLog > elInfo) then begin
    writeln(FRunLog^, pstDebg+s);
    result := true;
  end;
end;
{$endif}

procedure TinlConfiguration.DetachPlugins;
begin
  FActvPlugins.BeginUpdate;
end;

procedure TinlConfiguration.postSignal(snlRcpnt: TinlNameType; snlMsg: TinlStringType);
var
  i: integer;
begin
  if snlRcpnt='*' then for i := 0 to FActvPlugins.Count-1 do TinlPlugin(FActvPlugins[i]).ProceedSignal(snlMsg)
  else if FActvPlugins.Find(snlRcpnt,i) then TinlPlugin(FActvPlugins.Objects[i]).ProceedSignal(snlMsg)
  else doError('Destination:'+snlRcpnt+' for signal <'+snlMsg+'> not found.');
end;

function TinlConfiguration.GetNewID: TinlID;
begin
  { TODO : Написать механизм выдачи идентификаторов }
  result := 0;
end;

function TinlConfiguration.RegisterID(aID: TinlID): TinlID;
begin
  result := aID;
end;

{ TinlPlugin }

constructor TinlPlugin.Create(aType: TUnitType; aName: TinlNameType);
begin
  FUnitType := aType;
  FUnitName := aName;
  FConfiguration := nil;
  FPluged := false;
  FChilds := nil;
  FUnitLogPrfx := pstPlgn+pstDelim+FUnitName+pstDelim;
  FUnitCfgPrfx := FUnitName+cfgPrmDelim;
end;

destructor TinlPlugin.Destroy;
var
  i: integer;
begin
  if assigned(FChilds) then begin
    for i := FChilds.Count-1 downto 0 do TinlPlugin(FChilds[i]).Free;
    FreeAndNil(FChilds);
  end;
  inherited;
end;

function TinlPlugin.PlugIn(aCfg: TinlConfiguration): TinlLogicType;
begin
  result := false;
  if FPluged then exit;
  FConfiguration := aCfg;
  FPluged := true;
  result := true;
end;

function TinlPlugin.GetCfgParam(ParamInfo: PcfgParmtrInfo): TinlStringType;
begin
  if FPluged then result := FConfiguration.GetParam(ParamInfo);
end;

function TinlPlugin.GetLogicCfgParam(ParamName: TinlNameType; DefVal: TinlLogicType): TinlLogicType;
begin
  if FPluged then result := FConfiguration.GetLogicParam(ParamName, DefVal);
end;

function TinlPlugin.GetStringCfgParam(ParamName: TinlNameType; DefVal: TinlStringType): TinlStringType;
begin
  if FPluged then result := FConfiguration.GetStringParam(ParamName, DefVal);
end;

function TinlPlugin.GetIntegerCfgParam(ParamName: TinlNameType; DefVal: TinlIntegerType): TinlIntegerType;
begin
  if FPluged then result := FConfiguration.GetIntegerParam(ParamName, DefVal);
end;

procedure TinlPlugin.goError(s: TinlStringType);
begin
  if FPluged then FConfiguration.doError(FUnitLogPrfx+s);
end;

procedure TinlPlugin.goWarng(s: TinlStringType);
begin
  if FPluged then FConfiguration.doWarng(FUnitLogPrfx+s);
end;

procedure TinlPlugin.goHint(s: TinlStringType);
begin
  if FPluged then FConfiguration.doHint(FUnitLogPrfx+s);
end;

procedure TinlPlugin.goInfo(s: TinlStringType);
begin
  if FPluged then FConfiguration.doInfo(FUnitLogPrfx+s);
end;

{$ifdef iiDebugLog}
procedure TinlPlugin.goDebug(s: TinlStringType);
begin
  if FPluged then FConfiguration.doDebug(FUnitLogPrfx+s);
end;
{$endif}

procedure TinlPlugin.sndSignal(snlRcpnt: TinlNameType; snlMsg: TinlStringType);
begin
  if FPluged then FConfiguration.SendSignal(snlRcpnt, snlMsg);
end;

procedure TinlPlugin.regChild(aChild: TinlPlugin);
begin
  if FPluged then FConfiguration.RegPlugin(aChild);
  if not assigned(FChilds) then FChilds := TFPList.Create;
  FChilds.Add(aChild);
end;

{ TinlModule }

constructor TinlModule.Create(wCfg: TinlConfiguration);
begin
  inherited Create(modUnits[modType], modNames[modType]);
  wCfg.RegPlugin(Self);
  FUnitLogPrfx := pstMod+pstDelim+FUnitName+pstDelim;
  goInfo(logBgnMod+untName);

  DataInit;
end;

destructor TinlModule.Destroy;
begin
  DataDone;
  goInfo(logEndMod+untName);
  inherited;
end;

end.

